BearZPY Blog

Hi, nice to meet you

BearZPY's avatar BearZPY

xUtils3 的数据库使用

xUtils3 的数据库使用

xUtils3 是一款 Android ORM 和 IOC 快速应用开发框架,源自于 Afinal,对 Afinal 进行了大量重构,功能上也比 Afinal 更加强大。包括四个模块分别是 DbUtils,ViewUtils, HttpUtils 和 BitmapUtils 模块。项目主要使用了 DbUtils 模块实现的 ORM 框架,主要需求是将类数据整个读取或存入 SQLite 数据库中。

基本知识

ORM 框架:

ORM(Object Relational Mapping)框架采用元数据来描述对象间的关系映射细节,只要提供了持久化类与表的映射关系,ORM 框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。元数据是用来描述其它数据的数据 (data about other data),或者说是用于提供某种资源的有关信息的结构数据(structured data)。

DbUtils模块:

  • Android中的 ORM 框架,一行代码就可以进行增删改查;
  • 支持事务,默认关闭;
  • 可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);
  • 支持绑定外键,保存实体时外键关联实体自动保存或更新;
  • 自动加载外键关联实体,支持延时加载;
  • 支持链式表达查询,更直观的查询语义

使用准备

导入依赖

Gradle 构建时添加如下依赖即可使用该开源库

compile 'org.xutils:xutils:3.5.0'

配置相关权限

使用 xUtils3 时需要在 manifest 里添加相关权限,主要是 xUtils3 的其他模块会用到。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

初始化 xUtils3 模块

xUtils3 需要在 Application 的 OnCreate() 方法中进行初始化,所以我们需要使用自定义一个继承 Application 的 App 类。

public class App extends Application{

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化 xUtil3
        x.Ext.init(this);
        x.Ext.setDebug(BuildConfig.DEBUG);
    }
}

在 manifest 里面使用我们自己定义的 App 类,下面代码省略了其他内容。

<application
    android:name=".App">
    <!-- 四大组件 -->
</application>

使用 DbUtils 模块

使用步骤

  • 使用注解创建数据表
  • 使用 DaoConfig 进行数据库的信息配置
  • x.getDb(daoConfig) 获取数据库实例进行增删改查

创建数据表

首先要知道是只有在你对数据库里面的操作涉及到这张表的操作时,会先判断当前的表是否存在,如果不存在,才会创建一张表,如果存在,才会进行相应的 CRUD 操作。

DbUtils 相关注解:

其中核心注解有两个,分别是 @Table@Column

@Check     check约束
@Column    列名
@Finder    一对多、多对一、多对多关系
@Foreign   外键
@Id        主键,当为 int 类型时,默认自增,非自增时,需要设置 id 的值
@NoAutoIncrement  不自增
@NotNull  不为空
@Table    表名
@Transient  不写入数据库表结构
@Unique     唯一约束

@Table:有属性 name 和 onCreated 两个属性。name 属性决定了该实体类映射的数据库表名,而 onCreated 属性则可以用来添加表一级的属性或约束,例如创建联和唯一索引等。

@Column:有 name、property、isId、autoGen 四个属性。name 属性决定了实体类属性对应的数据库字段名,property 属性可以用来添加数据库中字段一级的属性或约束条件例如 not null,索引等,isId 属性表示该字段是否是主键,默认为 false,autoGen 则表示为主键是否自增长,默认为 true,所以该字段只有在 isId 属性为 true 时有效。未加注 @Column 注解的字段将不映射 SQLite 字段。

示例:

@Table(name = "user")
public class User {

    @Column(name = "id", isId = true)
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "email")
    private String email;

    @Column(name = "time")
    private Date time;

    @Column(name = "date")
    private java.sql.Date date;

    // 此处省略 getter 和 setter
}

使用 DaoConfig 进行数据库的信息配置

  • 设置数据库名
  • 设置数据库版本
  • 开启事务
  • 设置数据库开启监听方法
  • 设置数据库更新监听方法

当数据版本变化时,DbManager.DbUpgradeListener() 会被调用,可以在其中对表结构进行修改。当数据库打开时开启 WAL, 对写入加速提升巨大。

private DbManager.DaoConfig daoConfig;

private MyDBManager() {
    daoConfig = new DbManager.DaoConfig()
            .setDbName("dao.db")
            .setDbVersion(1)
            .setAllowTransaction(true)
            .setDbOpenListener(new DbManager.DbOpenListener() {
                @Override
                public void onDbOpened(DbManager db) {
                    db.getDatabase().enableWriteAheadLogging();
                }
            })
            .setDbUpgradeListener(new DbManager.DbUpgradeListener() {
                @Override
                public void onUpgrade(DbManager db, int oldVersion, int newVersion) {
                    // db.addColumn(...);
                }
            });
}

数据库的增删改查

保存类到数据库中:

// 此处省略了 MyDBManager 单例模式的实现

public boolean test() {
    User user = new User();
    user.setName("yy");
    user.setEmail("12345678@qq.com");
    user.setTime(new Date());
    user.setDate(new java.sql.Date(System.currentTimeMillis()));
    boolean ret = MyDBManager.getInstance().save(user);
    return ret;
}

public boolean save(Object object) {
    DbManager dbManager = x.getDb(daoConfig);
    try {
        dbManager.save(object);
        return true;
    } catch (DbException e) {
        e.printStackTrace();
    }
    return false;
}

根据列名查找匹配的第一个值,把该行数据从数据库中读取到类中:

// 此处省略了 MyDBManager 单例模式的实现

public void test() {
    User userFirst = (User) MyDBManager.getInstance()
                        .readFirst(User.class, "name", "xiao ming");
    Log.v(LOG_TAG, "userFirst = " + userFirst.toString());
}

public Object readFirst(Class<?> entityType, String columnName, String columnValue) {
    DbManager dbManager = x.getDb(daoConfig);
    try {
        WhereBuilder builder = WhereBuilder.b(columnName, "=", columnValue);
        return dbManager.selector(entityType)
                .orderBy("id", true).where(builder).findFirst();
    } catch (DbException e) {
        e.printStackTrace();
    }
    return null;
}

根据列名查找匹配的所有值的行数,并全部删除:

// 此处省略了 MyDBManager 单例模式的实现

public boolean test() {
    ret = MyDBManager.getInstance().delete(User.class,
                        "name", "xiao ming");
    return ret;
}

public boolean delete(Class<?> entityType, String columnName, String columnValue) {
    boolean result;
    DbManager dm = x.getDb(daoConfig);
    try {
        WhereBuilder builder = WhereBuilder.b(columnName, "=", columnValue);
        dm.delete(entityType, builder);
        result = true;
    } catch (DbException e) {
        result = false;
        e.printStackTrace();
    }
    return result;
}

直接使用 SQL 语句:

DbManager dm = x.getDb(daoConfig);

// 执行查询语句
Cursor cursor= dm.execQuery("select * from user where id>=5;");

// 执行非查询语句
dm.execNonQuery("DROP TABLE user");